/*
 * Copyright (C) 2009 Las Cumbres Observatory (lcogt.net)
 *
 * This program is free software; you can redistribute it and/or
 * modify it under the terms of the GNU General Public License
 * as published by the Free Software Foundation; either version 2
 * of the License, or (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
 */
package org.lcogt.tools.fitsviewer.client;

import gwt.canvas.client.Canvas;

import com.google.gwt.core.client.EntryPoint;
import com.google.gwt.core.client.GWT;
import com.google.gwt.event.dom.client.ClickEvent;
import com.google.gwt.event.dom.client.ClickHandler;
import com.google.gwt.event.dom.client.MouseDownEvent;
import com.google.gwt.event.dom.client.MouseDownHandler;
import com.google.gwt.event.logical.shared.BeforeSelectionEvent;
import com.google.gwt.event.logical.shared.BeforeSelectionHandler;
import com.google.gwt.event.logical.shared.ResizeEvent;
import com.google.gwt.event.logical.shared.ResizeHandler;
import com.google.gwt.gen2.picker.client.SliderBar;
import com.google.gwt.user.client.Window;
import com.google.gwt.user.client.rpc.AsyncCallback;
import com.google.gwt.user.client.ui.AbsolutePanel;
import com.google.gwt.user.client.ui.Button;
import com.google.gwt.user.client.ui.CheckBox;
import com.google.gwt.user.client.ui.FlexTable;
import com.google.gwt.user.client.ui.HasHorizontalAlignment;
import com.google.gwt.user.client.ui.HasVerticalAlignment;
import com.google.gwt.user.client.ui.HorizontalPanel;
import com.google.gwt.user.client.ui.Hyperlink;
import com.google.gwt.user.client.ui.Image;
import com.google.gwt.user.client.ui.KeyboardListener;
import com.google.gwt.user.client.ui.Label;
import com.google.gwt.user.client.ui.LoadListener;
import com.google.gwt.user.client.ui.MouseListenerAdapter;
import com.google.gwt.user.client.ui.PopupPanel;
import com.google.gwt.user.client.ui.RootPanel;
import com.google.gwt.user.client.ui.ScrollPanel;
import com.google.gwt.user.client.ui.TabBar;
import com.google.gwt.user.client.ui.TextBox;
import com.google.gwt.user.client.ui.Tree;
import com.google.gwt.user.client.ui.VerticalPanel;
import com.google.gwt.user.client.ui.Widget;
import com.google.gwt.user.client.ui.FlexTable.FlexCellFormatter;



public class FitsViewer implements EntryPoint {
	
	public static class GraphPopup extends PopupPanel{
		public Canvas graphCanvas;
		public int left;
		public int top;
		public int width;
		public int height;
		public FlexTable flexTable;
		public AbsolutePanel container;
		public Label zeroLabel;
		public Label maxLabel;
		public GraphPopup(double[] data, int left,int top,int width,int height,int max,int fullWidth,String graphType,boolean showHalfMax)
		{
			super(true);
			container = new AbsolutePanel();
			graphCanvas = new Canvas(width,height);
			container.add(graphCanvas,25,2);
			container.setPixelSize(graphCanvas.getWidth()+20, graphCanvas.getHeight()+5);
			flexTable = new FlexTable();
			zeroLabel = new Label("0");
			maxLabel = new Label(""+ max);
			container.add(zeroLabel,15,(graphCanvas.getHeight()-7));
			container.add(maxLabel,0,2);
			flexTable.setWidget(0, 1, container);
			flexTable.setText(1, 1, graphType);
			Hyperlink closeLink = new Hyperlink();
			closeLink.setText("Close");
			closeLink.addClickHandler(new ClickHandler(){

				@Override
				public void onClick(ClickEvent event) {
					closePopup();
					
				}
				
			});
			
			flexTable.setWidget(2, 0, closeLink);
			flexTable.setText(0, 2, data.length+"px");
			flexTable.getCellFormatter().setVerticalAlignment(0, 2, HasVerticalAlignment.ALIGN_BOTTOM);
			flexTable.setText(1, 2, "Max :" + max);
			flexTable.setText(1, 3, "FWHM : " + fullWidth);

			setWidget(flexTable);
			
			this.top = top;
			this.left = left;
			this.width = width;
			this.height = height;
			graphCanvas.clear();
			graphCanvas.beginPath();
			graphCanvas.setStrokeStyle("black");
			for(int i = 0; i < data.length;i++)
			  {
				  if(i == 0)
				  {
					  graphCanvas.moveTo(i, height-data[i]);

				  }
				  else
					  graphCanvas.lineTo(i*(width/data.length), (height-(data[i])));
			  }
			  graphCanvas.stroke();
			  graphCanvas.beginPath();
			  graphCanvas.setStrokeStyle("red");
			  graphCanvas.moveTo(0, 0);
			  graphCanvas.lineTo(10, 0);
			  graphCanvas.moveTo(0, 150);
			  graphCanvas.lineTo(10, 150);
			  if(showHalfMax)
			  {
			  	graphCanvas.moveTo(0, height/2.0);
			  	graphCanvas.lineTo(width,height/2.0);
			  }
			  graphCanvas.stroke();
			  
			
		}
		public void resetData(double[] data,int left, int top,int width, int height,int max,int fullWidth, String graphType,boolean showHalfMax)
		{
			
			this.top = top;
			this.left = left;
			this.width = width;
			this.height = height;
			maxLabel.setText(""+max);
			Hyperlink closeLink = new Hyperlink();
			closeLink.setText("Close");
			closeLink.addClickHandler(new ClickHandler(){

				@Override
				public void onClick(ClickEvent event) {
					closePopup();
					
				}
				
			});
			flexTable.setWidget(2, 0, closeLink);
			
			flexTable.setText(0, 2, data.length+"px");
			flexTable.setText(1, 2, "Max :" + max);
			flexTable.setText(1, 3, "FWHM : " + fullWidth);
			
			graphCanvas.clear();
			graphCanvas.beginPath();
			graphCanvas.setStrokeStyle("black");
			  for(int i = 0; i < data.length;i++)
			  {
				  if(i == 0)
				  {
					  graphCanvas.moveTo(i*(width/data.length), height-data[i]);
				  }
				  else
					  graphCanvas.lineTo(i*(width/data.length), (height-(data[i])));
			  }
			  graphCanvas.stroke();
			  graphCanvas.beginPath();
			  graphCanvas.setStrokeStyle("red");
			  graphCanvas.moveTo(0, 0);
			  graphCanvas.lineTo(10, 0);
			  graphCanvas.moveTo(0, 150);
			  graphCanvas.lineTo(10, 150);
			  if(showHalfMax)
			  {
				  graphCanvas.moveTo(0, height/2.0);
				  graphCanvas.lineTo(width,height/2.0);
			  }
			  graphCanvas.stroke();
		}
		public void closePopup()
		{
			this.hide();
		}
	}
  
  private VerticalPanel mainPanel = new VerticalPanel();
  private HorizontalPanel menuPanel = new HorizontalPanel();
  private HorizontalPanel contentsPanel = new HorizontalPanel();
  
  private FlexTable specsFlexTable = new FlexTable();
  private FlexTable pictureFlexTable = new FlexTable();
  private FlexTable treeFlexTable;
  private TabBar treeTabBar;

  
  private Canvas canvas = new Canvas();
  private Canvas dummyCanvas = new Canvas();

  private Button editCrossHairButton = new Button("Cross Hair");
  private Button editLineProfileButton = new Button("Line Profile");
  
  private Button viewHorizGraphButton = new Button("Horiz Graph");
  private Button viewVertGraphButton = new Button("Vert Graph");
  
  private Button zoom2Button = new Button("2x");
  private Button zoom4Button = new Button("4x");
  
  
  private Button displayHeaderButton = new Button("Show Header");
  private Button openSimailarButton = new Button("Find Similar Images");
  
  private Button findFitsButton = new Button("Find Fits");
  private TextBox findFitsBox = new TextBox();
  
  private Hyperlink settingsLink;
  private Hyperlink closeSettingsLink;
  private Hyperlink closeHeaderLink;
  private CheckBox dockGraphs;
  private CheckBox showHalfMax;
  
  private CheckBox tagID= new CheckBox("Tag ID");
  private CheckBox propID = new CheckBox("Proposal ID");
  private CheckBox groupID = new CheckBox("Group ID");
  private CheckBox obsID = new CheckBox("Observation ID");
  private CheckBox userID = new CheckBox("User ID");
  private CheckBox target = new CheckBox("Target");
  
  private PopupPanel headerPanel;
  private PopupPanel similarPanel;
  private PopupPanel loadPanel;
  private GraphPopup horizGraphPopup;
  private GraphPopup verticalGraphPopup;
  private GraphPopup lineProfileGraph;
  private PopupPanel settingsPanel;
  
  private Tree imageTree;
  private Tree selectedImageTree;
  private VerticalPanel xyPanel;
  private Label xPosLabel;
  private Label yPosLabel;
  private ScrollPanel scrollPanel;
  private boolean isVertGraphShowing = false;
  private boolean isHorizGraphShowing = false;
  private boolean isCrossHairEnabled = false;
  private boolean isLineProfileEnabled = false;
  private boolean isMouseDown = false;
  private boolean zoomLoaded = false;
  
  private String basePath="";
  private String fitsPath="";
  private String jpgPath = "";
  
  private int xPos = 0;
  private int yPos = 0;
  private int clickStartXPos=0;
  private int clickStartYPos=0;
  private int clickEndXPos= 0;
  private int clickEndYPos= 0;
  private int zoom = 2;
  private Image fitsImage;
  private Image backgroundImage;
  
  private int imageHeight=1;
  private int imageWidth=1;
  
  private Image zoomImage=null;
  private SliderBar slider;
  
  private int zoomImageHeight= 100;
  private int zoomImageLength = 100;
  private int popupGraphHeight = 150;
  private int popupGraphWidth = 200;
  
  private String scrollPanelHeight = "600";
  private String scrollPanelWidth = "225";
  
  private String zoomImageBaseURL;
  private boolean ctrlDown = false;
  private boolean backgroundLoaded = false;
  
  
  FitsDataServiceAsync fitsServiceSvc;
  ZoomJpegServiceAsync zoomJpegServiceSvc;
  TreeDataServiceAsync treeDataServiceSvc;
  FitsHeaderServiceAsync fitsHeaderServiceSvc;
  LinkToJPGServiceAsync linkToJpgServiceSvc;
  GetRelatedServiceAsync getRelatedServiceSvc;
  FitsIDServiceAsync fitsIDServiceSvc;
  /**
   * Entry point method.
   */
  
  public void onModuleLoad() {
	  createServices();
	  buildSetup();
	  buildSettingsPanel();
	  buildSimilarPanel();
	  
	  /*
	   * Creates popup to indicate when jpgs are being created
	   */
	  loadPanel = new PopupPanel();
	  Label loadLabel = new Label("Please Allow a moment to Create Jpgs");
	  loadPanel.add(loadLabel);
	  
	  /*
	   * Checks to see whether there is an input in the url
	   */
	  final AsyncCallback<String[]> relatedCallback = new AsyncCallback<String[]>(){

		@Override
		public void onFailure(Throwable caught) {
			Window.alert(caught.toString());
		}

		@Override
		public void onSuccess(String[] result) {
			if(result.length == 1)
			{
				FitsTreeItem currentNode = (FitsTreeItem)imageTree.getItem(0);
				currentNode.removeItems();
				currentNode.setFullyLoaded(false);
				currentNode.setState(true);
				String[] pathParts = result[0].split("/");
				for(int i = 0; i <pathParts.length;i++)
				{
					FitsTreeItem child = new FitsTreeItem(pathParts[i].toLowerCase());
					currentNode.addItem(child);
					child.setState(true);
					if(currentNode.getText().equals("Fits Images"))
					{
						if(child.getText().contains(".fits"))
						{
							child.setJpgPath("/jpg/"+ parseFitsToString(child.getText()));
							fitsImage.prefetch(basePath+child.getJpgPath());
						}
						else
							child.setJpgPath(child.getText());
						child.setPath(child.getText());
					}
					else
					{
						if(child.getText().contains(".fits"))
							child.setJpgPath(currentNode.getJpgPath()+"/jpg/"+ parseFitsToString(child.getText()));
						else
							child.setJpgPath(currentNode.getJpgPath()+"/"+child.getText());
						child.setPath(currentNode.getPath()+"/"+child.getText());
					}
					currentNode.setState(true);
					currentNode = child;
					
					
				}
				imageTree.setSelectedItem(currentNode);
				nodeClick(currentNode);
				

				}
				loadPanel.hide();
			}
			
		
		  
	  };
	  String parameters = getURLParameters();
	  
	  if(parameters.contains(".fits"))
	  {
		  String[] inputs = {parameters.substring(1),"None","None","None","None","None","None","None","None","None","None"};
		  loadPanel.center();
		  getRelatedServiceSvc.getRelatedFits(inputs, relatedCallback);
	  }
	  AsyncCallback<String> callback = new AsyncCallback<String>() {
	    public void onFailure(Throwable caught) {
		    	Window.alert("Fail");
	    }

		public void onSuccess(String result) {
			basePath = result;
		}
	  };
	  linkToJpgServiceSvc.getJpgLink(callback);
	  
	  //Image that gets pixel size of a jpg image
	  backgroundImage = new Image();
	  backgroundImage.setVisible(false);
	  
	  //initializes zoom image
	  zoomImage = new Image();
	  canvas.setBackgroundColor(Canvas.TRANSPARENT);
	  
	  /*
	   * Sets up the settings link
	   */
	  settingsLink = new Hyperlink();
	  settingsLink.setText("Settings");
	  settingsLink.addStyleDependentName("clickable");
	  closeHeaderLink= new Hyperlink();
	  closeHeaderLink.setText("Close");
	  closeHeaderLink.addStyleDependentName("clickable");
	  
	  headerPanel = new PopupPanel();
	  
	  fitsImage.addLoadListener(new LoadListener(){
			
			@Override
			public void onError(Widget sender) {
				Window.alert("Image Fail");
				canvas.setSize("0", "0");
				
			}

			@Override
			public void onLoad(Widget sender) {
				fitsImage.setVisible(true);
				//imageHeight = fitsImage.getHeight();
				//imageWidth = fitsImage.getWidth();
				double maxHeightRatio = (Window.getClientHeight()-pictureFlexTable.getAbsoluteTop())/(double)fitsImage.getHeight();
				fitsImage.setPixelSize((int)(fitsImage.getWidth()*maxHeightRatio), (int)(fitsImage.getHeight()*maxHeightRatio));
				RootPanel.get().setWidgetPosition(settingsLink, Window.getClientWidth()-50, 0);
				scrollPanel.setHeight(""+(fitsImage.getHeight()-30));
				canvas.setPixelSize(fitsImage.getWidth()-1, fitsImage.getHeight()-1);
				RootPanel.get().add(canvas, fitsImage.getAbsoluteLeft(),fitsImage.getAbsoluteTop());
				getFitsHeader();
			}
			  
		  }); 
	  backgroundImage.addLoadListener(new LoadListener(){

		@Override
		public void onError(Widget sender) {
			Window.alert("Failed to load background image");
			
		}

		@Override
		public void onLoad(Widget sender) {
			//Window.alert("Background Image Load");
			imageHeight = backgroundImage.getHeight();
			imageWidth = backgroundImage.getWidth();
			setMagnifyPannel(jpgPath,zoom,backgroundImage.getWidth(),backgroundImage.getHeight());
			backgroundLoaded = true;
			
		}
		  
	  });

	  // Associate the Main panel with the HTML host page.
	  RootPanel.get("FitsViewer").add(mainPanel);
	  RootPanel.get().add(settingsLink, Window.getClientWidth()-50, 0);
	  RootPanel.get().add(backgroundImage,0,0);
	  
	  //Adds a Handler to resize the Image everytime the window is resized
	  Window.addResizeHandler(new ResizeHandler(){
		public void onResize(ResizeEvent event) {
			double maxHeightRatio = (Window.getClientHeight()-fitsImage.getAbsoluteTop())/(double)imageHeight;
			double ratio = maxHeightRatio;
			fitsImage.setPixelSize((int)(imageWidth*ratio), (int)(imageHeight*ratio));
			scrollPanel.setHeight(""+(fitsImage.getHeight()-30));
			canvas.setPixelSize(fitsImage.getWidth()-1, fitsImage.getHeight()-1);
			RootPanel.get().setWidgetPosition(settingsLink, Window.getClientWidth()-50, 0);
		}
		  
	  });
	   
	  //selectedImageTree is a tree that holds any selected images or images from a similar queue
	  selectedImageTree = new Tree();
	  final FitsTreeItem selectedRoot = new FitsTreeItem("Selected Images");
	  selectedImageTree.addItem(selectedRoot);
	  selectedRoot.setState(true);
	  
	  //Displays image selected on selectedImageTree
	  selectedImageTree.addMouseDownHandler(new MouseDownHandler(){

			@Override
			public void onMouseDown(MouseDownEvent event) {
				FitsTreeItem selectedNode = (FitsTreeItem)selectedImageTree.getSelectedItem();
				jpgPath = ((FitsTreeItem) selectedImageTree.getSelectedItem()).getJpgPath();
				fitsPath = ((FitsTreeItem) selectedImageTree.getSelectedItem()).getPath();
				selectedNode.setState(true);
			}
	    	
	    });
	  //adds keyboardlistener to listen for a ctrl down to add selected node to the selectedImageTree
	  imageTree.addKeyboardListener(new KeyboardListener(){

			@Override
			public void onKeyDown(Widget sender, char keyCode, int modifiers) {
				if (keyCode == KEY_CTRL)
					ctrlDown = true;
				
				
			}

			@Override
			public void onKeyPress(Widget sender, char keyCode, int modifiers) {
				if (keyCode == KEY_DOWN || keyCode == KEY_UP)
				{
					if(imageTree.getSelectedItem().getText().contains(".fits"))
					{
						if(settingsPanel.isShowing())
	                        settingsPanel.hide();
						zoomLoaded = false;
						specsFlexTable.setText(0,1,"Loading...");						  
						jpgPath=((FitsTreeItem) imageTree.getSelectedItem()).getJpgPath();
						fitsPath = ((FitsTreeItem) imageTree.getSelectedItem()).getPath();
						backgroundImage = new Image();
						backgroundImage.setUrl(basePath+((FitsTreeItem) (imageTree.getSelectedItem())).getJpgPath());
						fitsImage.setUrl(basePath+((FitsTreeItem) (imageTree.getSelectedItem())).getJpgPath());
					}
				}
				
			}

			@Override
			public void onKeyUp(Widget sender, char keyCode, int modifiers) {
				if(keyCode == KEY_CTRL)
					ctrlDown = false;
			}
	    	
	    });
	  	//adds keyboardlistener to listen for a ctrl down to remove selected node to the selectedImageTree
	    selectedImageTree.addKeyboardListener(new KeyboardListener(){

			@Override
			public void onKeyDown(Widget sender, char keyCode, int modifiers) {
				if(keyCode == KEY_CTRL)
					ctrlDown = true;
				
			}

			@Override
			public void onKeyPress(Widget sender, char keyCode, int modifiers) {
				if (keyCode == KEY_DOWN || keyCode == KEY_UP)
				{
					if(selectedImageTree.getSelectedItem().getText().contains(".fits"))
					{
						if(settingsPanel.isShowing())
	                        settingsPanel.hide();
						zoomLoaded = false;
						specsFlexTable.setText(0,1,"Loading...");						  
						jpgPath=((FitsTreeItem) selectedImageTree.getSelectedItem()).getJpgPath();
						fitsPath = ((FitsTreeItem) selectedImageTree.getSelectedItem()).getPath();
						//backgroundImage = new Image();
						backgroundImage.setUrl(basePath+((FitsTreeItem) (selectedImageTree.getSelectedItem())).getJpgPath());
						fitsImage.setUrl(basePath+((FitsTreeItem) (selectedImageTree.getSelectedItem())).getJpgPath());
					}
				}
				
			}

			@Override
			public void onKeyUp(Widget sender, char keyCode, int modifiers) {
				if(keyCode == KEY_CTRL)
					ctrlDown = false;
				
			}
	    	
	    });
	   //Displays image from selectedImageTree
	    selectedImageTree.addMouseDownHandler(new MouseDownHandler(){

			@Override
			public void onMouseDown(MouseDownEvent event) {
				FitsTreeItem selectedItem = (FitsTreeItem)selectedImageTree.getSelectedItem();
				if(selectedItem.getText().contains(".fits"))
				{
					  if(settingsPanel.isShowing())
						  settingsPanel.hide();
					  if(ctrlDown)
					  {
						  selectedItem.remove();
					  }
					  else
					  {
						  zoomLoaded = false;
						  specsFlexTable.setText(0,1,"Loading...");
						  
						  jpgPath=selectedItem.getJpgPath();
						  fitsPath = selectedItem.getPath();	
						  fitsImage.setVisible(true);
						  fitsImage.setUrl(basePath+jpgPath);
						  //backgroundImage = new Image();
						  backgroundImage.setUrl(basePath+jpgPath);
					  }
				}
			}
	    	
	    });
	    //Fills imageTree with directory or displays selected fits Image
	    imageTree.addMouseDownHandler(new MouseDownHandler(){

			@Override
			public void onMouseDown(MouseDownEvent event) {
				
				final FitsTreeItem selectedNode = (FitsTreeItem) imageTree.getSelectedItem();
				nodeClick(selectedNode);
			}
	    	
	    });
	    //Dont really like this treeTabBar. Doesnt work that well but just here for now.Need something that acts more like a tab bar
	    //Switches between imageTree and selectedImageTree
	    treeTabBar.addBeforeSelectionHandler(new BeforeSelectionHandler(){

			@Override
			public void onBeforeSelection(BeforeSelectionEvent event) {
				if(treeTabBar.getSelectedTab() == 0)
				{
					treeTabBar.setWidth(treeFlexTable.getOffsetWidth()+"");
					scrollPanel.setWidget(imageTree);
				}
				else
				{
					scrollPanel.setWidget(selectedImageTree);
					treeTabBar.setWidth(treeFlexTable.getOffsetWidth()+"");
				}
			}
	    	
	    });

	    
	    /*
	     * Handles all interaction with canvas
	     * Makes call to server for fits info depending on mode selected
	     */
	    canvas.addMouseListener(new MouseListenerAdapter(){
	    	public void onMouseMove(Widget sender, int x, int y)
	    	{
	    		if(zoomLoaded && backgroundLoaded)
	    		{
	    			specsFlexTable.setWidget(0,1,dummyCanvas);
	    			double newX = (x*((double)imageWidth/(double)fitsImage.getWidth()*zoom));
	    			double newY = (y*((double)imageHeight/(double)fitsImage.getHeight()*zoom));
	    			zoomImage.setVisibleRect((int)(newX-(zoomImageHeight/2)), (int)(newY-(zoomImageHeight/2)), zoomImageHeight, zoomImageHeight);
	    			specsFlexTable.setWidget(0, 1, zoomImage);	
	    		}
	    		if(!isCrossHairEnabled)
	    		{
	    			xPos = x;
	    			yPos = y;
	    			xPosLabel.setText("X :" + (int)(xPos*((double)imageWidth/(double)fitsImage.getWidth())));
	    			yPosLabel.setText("Y :" + (int)((canvas.getHeight()-yPos)*((double)imageHeight/(double)fitsImage.getHeight())));
	    		}
	    		if(isLineProfileEnabled && isMouseDown)
	    		{
	    			canvas.setStrokeStyle("GREEN");
	    			canvas.clear();
	    			canvas.beginPath();
	    			canvas.moveTo(clickStartXPos, clickStartYPos);
	    			canvas.lineTo(x, y);
	    			canvas.stroke();
	    		}
	    		
	    		
	    	}
	    	public void onMouseDown(Widget sender, int x, int y)
	    	{
	    		isMouseDown= true;
	    		if(isLineProfileEnabled)
	    		{
	    			clickStartXPos=x;
	    			clickStartYPos=y;
	    			
	    		}
	    		
	    		 if(isCrossHairEnabled)
	    		  {
	    			  canvas.setStrokeStyle("RED");
	    			  canvas.clear();
	    			  canvas.beginPath();
	    			  canvas.moveTo(0, y);
	    			  canvas.lineTo(canvas.getWidth(), y);
	    			  canvas.stroke();
	    			  canvas.moveTo(x, 0);
	    			  canvas.lineTo(x,canvas.getHeight());
	    			  canvas.stroke();
	    			  canvas.save();
	    			  xPos = x;
	    			  yPos = y;
	    			  xPosLabel.setText("X :" + (int)(xPos*((double)imageWidth/(double)fitsImage.getWidth())));
	    			  yPosLabel.setText("Y:" + (int)((canvas.getHeight()-yPos)*((double)imageHeight/(double)fitsImage.getHeight())));
	    			  refreshGraphs((int)(xPos*((double)imageWidth/(double)fitsImage.getWidth())),(int)((canvas.getHeight()-y)*((double)imageHeight/(double)fitsImage.getHeight())),1,1);//needs to be subtracted from the image because the orintation is different.
	    		  }
	    		 else
	    		 {
	    			// refreshGraphs(xPos,yPos);
	    		 }
	    	}
	    	public void onMouseUp(Widget sender, int x, int y)
	    	{
	    		isMouseDown= false;
	    		if(isLineProfileEnabled)
	    		{
	    			clickEndXPos=x;
	    			clickEndYPos=y;
	    			canvas.setStrokeStyle("GREEN");
	    			canvas.clear();
	    			canvas.beginPath();
	    			canvas.moveTo(clickStartXPos, clickStartYPos);
	    			canvas.lineTo(clickEndXPos, clickEndYPos);
	    			canvas.stroke();
	    			drawLineProfileGraph((int)(clickStartXPos*((double)imageWidth/(double)fitsImage.getWidth())),(int)((canvas.getHeight()-clickStartYPos)*((double)imageHeight/(double)fitsImage.getHeight())),(int)(clickEndXPos*((double)imageWidth/(double)fitsImage.getWidth())),(int)((canvas.getHeight()-clickEndYPos)*((double)imageHeight/(double)fitsImage.getHeight())));
	    		}
	    	}
	    });
	    /*
	     * Allows user to find fits image based on name typed into text box
	     * FitsImage must be in database
	     */
	    findFitsButton.addClickHandler(new ClickHandler(){

			@Override
			public void onClick(ClickEvent event) {
				String input = findFitsBox.getText();
				if(input.contains(".fits"))
				{
					String[] inputs = {input,"None","None","None","None","None","None","None","None","None","None"};
					getRelatedServiceSvc.getRelatedFits(inputs, relatedCallback);
				}
				
			}
	    	
	    });
		
	    /*
	     * Switches to Line Profile mode
	     */
		editLineProfileButton.addClickHandler(new ClickHandler(){
			public void onClick(ClickEvent event){
				toggleLineProfile();
			}
		});
		//Switches to Cross Hair mode
		editCrossHairButton.addClickHandler(new ClickHandler() {
			public void onClick(ClickEvent event) {
			toggleCrossHair();
		}
	});
		viewHorizGraphButton.setTitle("Acivates Horizontal Graph in CrossHair Mode");
	//Allows Horizontal graph to be visable
  		viewHorizGraphButton.addClickHandler(new ClickHandler() {
  		public void onClick(ClickEvent event) {
  			changeHorizGraph();
  		}
  	});
  		
  		viewVertGraphButton.setTitle("Acivates Vertical Graph in CrossHair Mode");
  	//Allows Vertical Graph to be visable
  		viewVertGraphButton.addClickHandler(new ClickHandler() {
  		public void onClick(ClickEvent event) {
  			changeVertGraph();
  		}
  	});
  		
  		
  		//Switches Zoomed Image to 2x Zoom
  		zoom2Button.addClickHandler(new ClickHandler(){
  			public void onClick(ClickEvent event){
  				zoom2pressed();
  			}
  		});
  		//Switches Zoomed Image to 4x Zoom
  		zoom4Button.addClickHandler(new ClickHandler(){
  			public void onClick(ClickEvent event){
  				zoom4pressed();
  			}
  		});
  		//Pops up Settings Popup
  		settingsLink.addClickHandler(new ClickHandler(){
  			public void onClick(ClickEvent event){
  				displaySettings();
  			}
  		});
  		//Closes Settings Popup
  		closeSettingsLink.addClickHandler(new ClickHandler(){

			@Override
			public void onClick(ClickEvent event) {
				closeSettings();	
			}
  		});
  		//Closes Header Popup
  		closeHeaderLink.addClickHandler(new ClickHandler(){

			@Override
			public void onClick(ClickEvent event) {
				closeHeader();
			}
  			
  		});
  		//Docks graphs in the top of the browser
		dockGraphs.addClickHandler(new ClickHandler(){
			public void onClick(ClickEvent event) {
				
			}
  		});
		//Displays Fits Header
		displayHeaderButton.addClickHandler(new ClickHandler(){
			public void onClick(ClickEvent event){
				displayHeader();
			}
		});
		//Opens popup to select attributes to find similar images
		openSimailarButton.addClickHandler(new ClickHandler(){
			public void onClick(ClickEvent event){
				if(!imageTree.getSelectedItem().getText().contains(".fits"))
					Window.alert("Must Select a Fits Image");
				else
					fillSimilarImages();
			}
		});
  		
  }
  
private void buildSimilarPanel() {
	similarPanel = new PopupPanel();

	Button findSimilarButton = new Button("Find");

	Hyperlink IDholderClose = new Hyperlink();
	IDholderClose.setText("Close");
	findSimilarButton.addClickHandler(new ClickHandler(){

		@Override
		public void onClick(ClickEvent event) {
			getRelatedImages();
		}
		  
	  });
  
	IDholderClose.addClickHandler(new ClickHandler(){

		@Override
		public void onClick(ClickEvent event) {
			closeIDHolder();
		}
		  
	  });
	VerticalPanel IDHolder = new VerticalPanel();
	
	IDHolder.add(tagID);
	IDHolder.add(propID);
	IDHolder.add(groupID);
	IDHolder.add(obsID);
	IDHolder.add(userID);
	IDHolder.add(target);
	IDHolder.add(findSimilarButton);
	IDHolder.add(IDholderClose);

	similarPanel.add(IDHolder);

}

private void buildSettingsPanel() {
	  dockGraphs = new CheckBox("Dock Graphs");
	  dockGraphs.setTitle("Toggles whether the graphs will be displayed near cursor or docked at the top");
	  
	  slider = new SliderBar(0,30);
	  slider.setTitle("Adjusts how many pixels are to the right/up or left/down in Horizontal/Vertical mode");
	  slider.setStepSize(1);
	  slider.setCurrentValue(15);
	  slider.setNumTicks(31);
	  slider.setNumLabels(2);
	  slider.setSize("248px", editLineProfileButton.getOffsetHeight()+"px");
	  
	  showHalfMax = new CheckBox("Show Half Max");
	  showHalfMax.setTitle("Toggles whether a line for the half max will be displayed on the graphs");
	  
	  closeSettingsLink = new Hyperlink();
	  closeSettingsLink.setText("Close");
	  closeSettingsLink.addStyleDependentName("clickable");
	  
	  VerticalPanel settingsContainer = new VerticalPanel();
	  settingsContainer.addStyleDependentName("backgroudWhite");
	  settingsContainer.add(dockGraphs);
	  settingsContainer.add(showHalfMax);
	  settingsContainer.add(slider);
	  settingsContainer.add(closeSettingsLink);
	  settingsContainer.setCellHeight(slider, "50px");
	  
	  settingsPanel = new PopupPanel();
	  settingsPanel.add(settingsContainer);


}

private void buildSetup() {
	  
	  buildSpecsFlexTable();
	  buildMenuPanel();
	  buildContentsPanel();
	  buildPictureFlexTable();
	  
	  mainPanel.add(specsFlexTable);
	  mainPanel.add(menuPanel);
	  mainPanel.add(contentsPanel);
	  mainPanel.add(pictureFlexTable);
}
  /*
   * adds x,y postions, zoom buttons and zoomImage location
   */
  public void buildSpecsFlexTable()
  {
	  //Position labels
	  xPosLabel = new Label("X : ");
	  yPosLabel = new Label("Y : ");
	  xyPanel = new VerticalPanel();
	  xyPanel.add(xPosLabel);
	  xyPanel.add(yPosLabel);
	  
	  dummyCanvas.setPixelSize(zoomImageHeight, zoomImageLength);

	  VerticalPanel ZoomButtonHolder = new VerticalPanel();
	  zoom2Button.addStyleDependentName("enabled");
	  ZoomButtonHolder.add(zoom2Button);
	  ZoomButtonHolder.add(zoom4Button);
	  zoom2Button.setTitle("Click to change to Zoom x2");
	  zoom4Button.setTitle("Click to change to Zoom x4");
	  

	  specsFlexTable.setWidget(0, 0, xyPanel);
	  specsFlexTable.setWidget(0, 1, dummyCanvas);
	  specsFlexTable.setWidget(0, 3, ZoomButtonHolder);
	  specsFlexTable.getFlexCellFormatter().setWidth(0, 0, "50");
	  specsFlexTable.getCellFormatter().setHeight(0, 1, "100");
	  specsFlexTable.getCellFormatter().setWidth(0, 1, "100");
}
  public void buildMenuPanel()
  {
	  menuPanel.add(viewHorizGraphButton);
	  menuPanel.add(viewVertGraphButton);
	  menuPanel.add(displayHeaderButton);
	  menuPanel.add(openSimailarButton);
  }
  public void buildContentsPanel()
  {
	  findFitsBox.setWidth("250");
	  editLineProfileButton.setTitle("Activates LineProfile Mode");
	  editCrossHairButton.setTitle("Activates CrossHair Mode");
		
	  contentsPanel.add(editCrossHairButton);
	  contentsPanel.add(editLineProfileButton);
	  contentsPanel.add(findFitsBox);
	  contentsPanel.add(findFitsButton);
  }
public void buildPictureFlexTable()
  {
	  fitsImage = new Image();
	  fitsImage.setVisible(false);
	  
	  treeTabBar = new TabBar();
	  treeTabBar.addTab("Image Tree");
	  treeTabBar.addTab("Selected Images");
	  treeTabBar.addStyleName("background");
	  
	  FitsTreeItem root = new FitsTreeItem("Fits Images");
	  imageTree = new Tree();
	  imageTree.addItem(root);

	  scrollPanel = new ScrollPanel(imageTree);
	  scrollPanel.setSize(scrollPanelWidth, scrollPanelHeight);
	  
	  treeFlexTable = new FlexTable();
	  treeFlexTable.setText(0,0, "Click on Fits Images to Start File View:");
	  treeFlexTable.setWidget(1,0,scrollPanel);
	  treeFlexTable.addStyleName("addBorder");
	  
	  
	  pictureFlexTable.setWidget(1, 1, fitsImage);
	  pictureFlexTable.setWidget(0, 0, treeTabBar);
	  pictureFlexTable.setWidget(1, 0, treeFlexTable);
	  FlexCellFormatter formatter = pictureFlexTable.getFlexCellFormatter();
	  formatter.setVerticalAlignment(1, 0, HasVerticalAlignment.ALIGN_TOP);
	  formatter.setHorizontalAlignment(1, 0, HasHorizontalAlignment.ALIGN_LEFT);
	  formatter.setVerticalAlignment(1, 1, HasVerticalAlignment.ALIGN_TOP);
	  formatter.setHorizontalAlignment(1, 1, HasHorizontalAlignment.ALIGN_LEFT);
  }

public void displaySettings()
  {
	  if(settingsPanel.isShowing())
	  {
		  settingsPanel.hide();
		  return;
	  }
	  settingsPanel.center();
  }
  public void closeSettings()
  {
	  settingsPanel.hide();
  }
  public void closeIDHolder()
  {
	  similarPanel.hide();
  }
  public void displayHeader()
  {
	  headerPanel.center();
  }
  public void closeHeader()
  {
	  headerPanel.hide();
  }
  public void fillSimilarImages()
  {
	  similarPanel.center();
  }
  //Toggles the View Contents
  public void toggleViewContents()
  {
	  contentsPanel.clear();
	  contentsPanel.add(viewHorizGraphButton);
	  contentsPanel.add(viewVertGraphButton);
  }
  
  
  //Toggles the Edit Contents
  public void toggleEditContents()
  {
	  contentsPanel.clear();
	  contentsPanel.add(editCrossHairButton);
	  contentsPanel.add(editLineProfileButton);
  }
  //Toggles the CrossHair
  public void toggleCrossHair()
  {
	  if(isCrossHairEnabled)
	  {
		  isCrossHairEnabled = false;
		  canvas.clear();
		  editCrossHairButton.removeStyleDependentName("enabled");
	  }
	  else
	  {
		  isCrossHairEnabled = true;
		  editCrossHairButton.addStyleDependentName("enabled");
		  editLineProfileButton.removeStyleDependentName("enabled");
		  isLineProfileEnabled = false;
	  }
		  
  }
  public void toggleLineProfile()
  {
	  if(isLineProfileEnabled)
	  {
		  isLineProfileEnabled=false;
		  canvas.clear();
		  lineProfileGraph.hide();
		  editLineProfileButton.removeStyleDependentName("enabled");
	  }
		  
	  else
	  {
		  isLineProfileEnabled = true;
		  editLineProfileButton.addStyleDependentName("enabled");
		  editCrossHairButton.removeStyleDependentName("enabled");
		  isCrossHairEnabled = false;
	  }
  }
  //Toggles the Horizontal Graph
  public void changeHorizGraph()
  {
	  if(isHorizGraphShowing)
	  {
		  isHorizGraphShowing = false;
		  horizGraphPopup.hide();
		  viewHorizGraphButton.removeStyleDependentName("enabled");
	  }
	  else
	  {
		  isHorizGraphShowing = true;
		  viewHorizGraphButton.addStyleDependentName("enabled");
	  }
  }
  //Toggles the Vertical Graph
  public void changeVertGraph()
  {
	  if(isVertGraphShowing)
	  {
		  isVertGraphShowing = false;
		  verticalGraphPopup.hide();
		  viewVertGraphButton.removeStyleDependentName("enabled");
	  }
	  else
	  {
	  	  isVertGraphShowing = true;
		  viewVertGraphButton.addStyleDependentName("enabled");
	  } 
  }
  
  //Toggles the View Contents
  public void toggleZoomContents()
  {
	  contentsPanel.clear();
	  contentsPanel.add(zoom2Button);
	  contentsPanel.add(zoom4Button);
  }

  public void zoom2pressed()
  {
	  zoom=2;
	  specsFlexTable.setWidget(0,1, dummyCanvas);
	  zoomImage.setUrl(zoomImageBaseURL+ zoom +".jpg?" + System.currentTimeMillis());
	  zoomImage.setVisibleRect((xPos*zoom-(zoomImageHeight/2)), (yPos*zoom-(zoomImageLength/2)), zoomImageHeight, zoomImageLength);
	  zoom2Button.addStyleDependentName("enabled");
	  zoom4Button.removeStyleDependentName("enabled");
  }
  public void zoom4pressed()
  {
	  zoom = 4;
	  specsFlexTable.setWidget(0,1, dummyCanvas);
	  zoomImage.setUrl(zoomImageBaseURL+ zoom +".jpg?"+ System.currentTimeMillis());
	  zoomImage.setVisibleRect((xPos*zoom-(zoomImageHeight/2)), (yPos*zoom-(zoomImageLength/2)), zoomImageHeight, zoomImageLength);
	  zoom4Button.addStyleDependentName("enabled");
	  zoom2Button.removeStyleDependentName("enabled");

  }
  /*
   * refreshGraphs
   * calls server to get Fits data in the horizontal and vertical directions
   */
  public void refreshGraphs(int xPixel, int yPixel,int xEndPixel,int yEndPixel)
  {
	  if(fitsServiceSvc == null)
	   fitsServiceSvc = (FitsDataServiceAsync) GWT.create(FitsDataService.class);
	  AsyncCallback<int[]> xCallback = new AsyncCallback<int[]>() {
	    public void onFailure(Throwable caught) {
	    	//Window.alert("Didn't work");
	    }

		public void onSuccess(int[] result) {			
			//sets the data for the Horizonal Graph 
			if(isHorizGraphShowing)
			{
					double[] imgX = new double[result.length-2];
					for(int i = 0; i < imgX.length;i++)
					{
						imgX[i]= (double)result[i+2];
					}
					drawHorizGraphPopup(imgX,result[0],result[1]);
			}
		}
	  };
	  if(isHorizGraphShowing)
		  fitsServiceSvc.getFitsData(fitsPath, xPixel-(slider.getValue().intValue()), yPixel,xPixel+(slider.getValue().intValue()),yPixel,imageHeight,imageWidth, xCallback);// 10 is the offset for each direction. Should allow user to specify
	  
	  AsyncCallback<int[]> yCallback = new AsyncCallback<int[]>() {
		    public void onFailure(Throwable caught) {
		    	//Window.alert("Didn't work");
		    }

			public void onSuccess(int[] result) {
				//sets the data for the Vertical Graph 
				if(isVertGraphShowing)
				{
						double[] imgY = new double[result.length-2];
						for(int i = 0; i < imgY.length;i++)
						{
							imgY[i]= (double)result[i+2];
						}
						drawVertGraphPopup(imgY,result[0],result[1]);
				}
				
			}
		  };
		  if(isVertGraphShowing)
			  fitsServiceSvc.getFitsData(fitsPath, xPixel, yPixel-(slider.getValue().intValue()),xPixel,yPixel+(slider.getValue().intValue()),imageHeight,imageWidth, yCallback);//10 is the offset for each direction. Should allow user to specify how many pixels they want
  }
  /*
   * drawHorizGraphPopup
   * Method to scale and graph fits data and display in popup
   */
  public void drawHorizGraphPopup(double[] imgX,int max,int FWHM)
  {
	  for(int i = 0; i <imgX.length;i++)
	  {
		  imgX[i] = (double)((imgX[i]*popupGraphHeight))/(double)max;
	  }
	  if(horizGraphPopup == null)
		  horizGraphPopup = new GraphPopup(imgX,xPos,yPos,popupGraphWidth,popupGraphHeight,max,FWHM,"Horizontal Graph",showHalfMax.getValue());
	  else
		  horizGraphPopup.resetData(imgX, xPos, yPos, popupGraphWidth, popupGraphHeight,max,FWHM,"Horizontal Graph",showHalfMax.getValue());
	  if(dockGraphs.getValue())
		  horizGraphPopup.setPopupPosition(menuPanel.getAbsoluteLeft()+menuPanel.getOffsetWidth(), 0);
	  else
		  horizGraphPopup.setPopupPosition(xPos + canvas.getAbsoluteLeft()+10, yPos + canvas.getAbsoluteTop()+0);
	  horizGraphPopup.show();
  }
  /*
   * drawVertGraphPopup
   * Method to scale and graph fits data and display in popup
   */
  public void drawVertGraphPopup(double[] imgY,int max,int FWHM)
  {
	  for(int i = 0; i <imgY.length;i++)
	  {
		  imgY[i] = (double)((imgY[i]*popupGraphHeight))/(double)max;
	  }
	  if(verticalGraphPopup == null)
		  verticalGraphPopup = new GraphPopup(imgY,xPos,yPos,popupGraphWidth,popupGraphHeight,max,FWHM,"Vertical Graph",showHalfMax.getValue());
	  else
		  verticalGraphPopup.resetData(imgY, xPos, yPos, popupGraphWidth, popupGraphHeight,max,FWHM,"Vertical Graph",showHalfMax.getValue());
	  if(dockGraphs.getValue())
		  verticalGraphPopup.setPopupPosition(menuPanel.getAbsoluteLeft()+menuPanel.getOffsetWidth()+horizGraphPopup.getOffsetWidth(),0);
	  else
		  verticalGraphPopup.setPopupPosition(xPos + canvas.getAbsoluteLeft()+ 10, canvas.getAbsoluteTop() + yPos - 225);
	  verticalGraphPopup.show();
		  
  }
  
  /*
   * drawLineProfileGraph
   * Method makes call to server to get information after a line profile has been drawn
   */
  public void drawLineProfileGraph(int xStart,int yStart,int xEnd,int yEnd)
  {
	  AsyncCallback<int[]> lineProfileCallback = new AsyncCallback<int[]>() {
		    public void onFailure(Throwable caught) {
		    	//Window.alert("Didn't work");
		    }

			public void onSuccess(int[] result) {
				int max = result[0];
				int fullWidth = result[1];
				double[] doubleResult = new double[result.length-2];
				for(int i = 0; i < doubleResult.length;i++)
				{
					doubleResult[i]= (double)result[i+2];
				}
				drawLineProfileGraphPopup(doubleResult,max,fullWidth);
				
			}
		  };
		  fitsServiceSvc.getFitsData(fitsPath, xStart, yStart,xEnd,yEnd,imageHeight,imageWidth, lineProfileCallback);
  }
  /*
   * drawLineProfileGraphPopup
   * Method to scale and graph fits data and display in a Popup
   */
  public void drawLineProfileGraphPopup(double[] lineProfile,int max,int fullWidth)
  {
	  for(int i = 0; i <lineProfile.length;i++)
	  {
			  lineProfile[i] = (double)((lineProfile[i]*popupGraphHeight))/(double)max;
	  }
	  if(lineProfileGraph == null)
		  lineProfileGraph = new GraphPopup(lineProfile,xPos,yPos,popupGraphWidth,popupGraphHeight,max,fullWidth,"Line Profile Graph",showHalfMax.getValue());
	  else
		  lineProfileGraph.resetData(lineProfile, xPos, yPos, popupGraphWidth, popupGraphHeight,max,fullWidth,"Line Profile Graph",showHalfMax.getValue());
	  if(xPos-popupGraphWidth < 0)
	  {
		  if(dockGraphs.getValue())
			  lineProfileGraph.setPopupPosition(menuPanel.getAbsoluteLeft()+menuPanel.getOffsetWidth(), 0);
		  else
			  lineProfileGraph.setPopupPosition(0,canvas.getAbsoluteTop() + yPos -popupGraphHeight);
	  }
	  else
	  {
		  if(dockGraphs.getValue())
			  lineProfileGraph.setPopupPosition(zoom2Button.getAbsoluteLeft()+zoom2Button.getOffsetWidth(), 0);
		  else
			  lineProfileGraph.setPopupPosition(xPos -popupGraphWidth, canvas.getAbsoluteTop() + yPos - popupGraphHeight);
	  }
	  lineProfileGraph.show();
  }
  /*
   * setMagnifyPannel
   * Method to call server to create zoomed images
   */
  public void setMagnifyPannel(String image,  int z, int width, int length)
  {
	  AsyncCallback<String> magnifyCallback = new AsyncCallback<String>() {
		    public void onFailure(Throwable caught) {
				
		    }

			public void onSuccess(String result) {
				zoomImageBaseURL = result;
				zoomImage.setUrl(zoomImageBaseURL+ zoom +".jpg?" + System.currentTimeMillis());
				zoomImage.setVisibleRect((int)(xPos*((double)imageWidth/fitsImage.getWidth())*zoom-(zoomImageHeight/2)), (int)(yPos*((double)imageHeight/fitsImage.getHeight())*zoom-(zoomImageLength/2)), zoomImageHeight, zoomImageLength);
				specsFlexTable.setText(0,1,"  ");
				zoomLoaded = true;
			}
		  };
	  
		  zoomJpegServiceSvc.getZoomJpeg(image,z,width,length, magnifyCallback);
  }
  /*
   * getTreeNodes
   * Method to call treeNodeService to get elements in a directory
   */
  public void getTreeNodes(String pathName,AsyncCallback callback)
  {
		  treeDataServiceSvc.getTreeData(pathName, callback);	
  }
  /*
   * parseFitsToString()
   * Method that returns .fits extension string to a .jpg extension
   */
  public String parseFitsToString(String input)
  {
			return input.replace("fits", "jpg");
  }
  /*
   * getFitsHeader()
   * Method to set Fits Header into headerPanel
   */
  public void getFitsHeader()
  {
	 if(fitsHeaderServiceSvc == null)
	   fitsHeaderServiceSvc = (FitsHeaderServiceAsync) GWT.create(FitsHeaderService.class);

	  AsyncCallback<String[]> callback = new AsyncCallback<String[]>() {
	    public void onFailure(Throwable caught) {
		    	Window.alert("Fail");
	    }

		public void onSuccess(String[] result) {
			headerPanel.clear();
			VerticalPanel holder = new VerticalPanel();
			ScrollPanel scrollResults = new ScrollPanel();
			FlexTable vertPanel = new FlexTable();
			scrollResults.add(vertPanel);
			Label headerLabel = new Label("Fits Header");
			holder.add(headerLabel);
			//vertPanel.setWidget(0, 0, headerLabel);
			headerLabel.setHorizontalAlignment(HasHorizontalAlignment.ALIGN_CENTER);
			headerLabel.addStyleDependentName("bold");
			for(int i = 0; i < result.length-1;i++)
			{
				String[] parts = result[i].split("=");
				Label label = new Label(parts[0]);
				label.addStyleDependentName("bold");
				Label label2 = new Label(parts[1]);
				//vertPanel.add(label);
				vertPanel.setWidget(i+1, 0, label);
				vertPanel.setWidget(i+1, 1, label2);
			}
			holder.add(scrollResults);
			scrollResults.setPixelSize(400, 600);
			holder.add(closeHeaderLink);
			headerPanel.add(holder);
			
		}
	  };

	  fitsHeaderServiceSvc.getFitsHeader(fitsPath,callback); 
  }
  /*
   * closeAllPopups()
   * Method to close any open popups
   */
  public void closeAllPopups()
  {
	  if(horizGraphPopup.isShowing())
		  horizGraphPopup.hide();
	  if(verticalGraphPopup.isShowing())
		  verticalGraphPopup.hide();
	  if(lineProfileGraph.isShowing())
		  lineProfileGraph.hide();
	  if(settingsPanel.isShowing())
		  settingsPanel.hide();
	  if(similarPanel.isShowing())
		  similarPanel.hide();
	  if(headerPanel.isShowing())
		  headerPanel.hide();
  }
  //javascript method for getting parameters after "?" in the url
  public static native String getURLParameters() /*-{ 
  return $doc.location.search;
}-*/;
  public void nodeClick(FitsTreeItem input){
	  loadPanel.center();
	  final FitsTreeItem selectedNode = input;
	  final FitsTreeItem selectedRoot = (FitsTreeItem) imageTree.getItem(0);
	  treeFlexTable.setText(0,0, "Click on Fits File to Open :");
		AsyncCallback<String[]> treeCallback = new AsyncCallback<String[]>() {
		    public void onFailure(Throwable caught) {
		    	//Window.alert("FAIL");
		    }

			public void onSuccess(String[] result) {
				loadPanel.hide();
				for(int i = 0; i < result.length;i++)
				{
					if(result[i].indexOf("jpg")<0 && result[i].indexOf("JPG") < 0 && result[i].indexOf(".DS_Store")<0 && result[i].indexOf("ZoomImages") < 0 && result[i].length() > 0 && !nodeInTree(selectedNode,result[i]))
					{
						FitsTreeItem child = new FitsTreeItem(result[i]);
						selectedNode.addItem(child);
						if(selectedNode.getText().equals("Fits Images"))
						{
							if(child.getText().contains(".fits"))
							{
								child.setJpgPath("/jpg/"+ parseFitsToString(child.getText()));
								fitsImage.prefetch(basePath+child.getJpgPath());
							}
							else
								child.setJpgPath(child.getText());
							child.setPath(child.getText());
						}
						else
						{
							if(child.getText().contains(".fits"))
							{
								child.setJpgPath(selectedNode.getJpgPath()+"/jpg/"+ parseFitsToString(child.getText()));
							}
							else
								child.setJpgPath(selectedNode.getJpgPath()+"/"+child.getText());
							child.setPath(selectedNode.getPath()+"/"+child.getText());
						}

					}
				}
				selectedNode.setState(true);
				selectedNode.setFullyLoaded(true);
			}
		  };
		String item = (String)selectedNode.getText();
		if(!selectedNode.isFullyLoaded()&&item.indexOf(".fits") < 0)
		{
			if(selectedNode.getText().equals("Fits Images"))
			{
				getTreeNodes("",treeCallback);
			}
				
			else
			{
				String filePath=selectedNode.getText();
				FitsTreeItem ptr = (FitsTreeItem) selectedNode.getParentItem();
				while(!ptr.getText().equals("Fits Images"))
				{
					filePath = ptr.getText()+ "/" + filePath;
					ptr = (FitsTreeItem) ptr.getParentItem();
				}
				getTreeNodes(filePath,treeCallback);
			}
			
		}
		else if(item.indexOf(".fits")>0)
		{
			if(ctrlDown)
			{
				FitsTreeItem newItem = new FitsTreeItem(selectedNode.getText());
				newItem.setPath(selectedNode.getPath());
				newItem.setJpgPath(selectedNode.getJpgPath());
				selectedRoot.addItem(newItem);
				selectedRoot.setState(true);
				fitsImage.prefetch(basePath+newItem.getJpgPath());
			}
			else
			{
				if(settingsPanel.isShowing())
                  settingsPanel.hide();
				if(headerPanel.isShowing())
					headerPanel.hide();
				  zoomLoaded = false;
				  specsFlexTable.setText(0,1,"Loading...");						  
				  jpgPath=selectedNode.getJpgPath();
				  fitsPath = selectedNode.getPath();
				  backgroundImage.setUrl(basePath+jpgPath);
				  fitsImage.setUrl(basePath+jpgPath);
				  AsyncCallback<String[]> callback = new AsyncCallback<String[]>() {
					    public void onFailure(Throwable caught) {
						    	Window.alert("Fail");
					    }

						public void onSuccess(String[] result) {
							loadPanel.hide();
							selectedNode.setTagID(result[0]);
							selectedNode.setPropID(result[0]);
							selectedNode.setGroupID(result[2]);
							selectedNode.setObsID(result[3]);
							selectedNode.setUserID(result[4]);
							selectedNode.setTarget(result[5]);
						}
					  };
					  fitsIDServiceSvc.getFitsID(fitsPath, callback);
			} 

		}
  }
  public boolean nodeInTree(FitsTreeItem node,String item)
  {
	for(int i = 0;i < node.getChildCount();i++)
	{
		if(node.getChild(i).getText().equals(item))
			return true;
	}
	return false;
	  
  }
  public void getRelatedImages()
  {
	  String[] inputs = {"None","None","None","None","None","None","None","None","None","None","None"};
	  if(tagID.getValue())
		  inputs[1]= ((FitsTreeItem) imageTree.getSelectedItem()).getTagID();
	  if(propID.getValue())
		  inputs[2]= ((FitsTreeItem) imageTree.getSelectedItem()).getPropID();
	  if(groupID.getValue())
		  inputs[3]= ((FitsTreeItem) imageTree.getSelectedItem()).getGroupID();
	  if(obsID.getValue())
		  inputs[4]= ((FitsTreeItem) imageTree.getSelectedItem()).getObsID();
	  if(userID.getValue())
		  inputs[5]= ((FitsTreeItem) imageTree.getSelectedItem()).getUserID();
	  if(target.getValue())
		  inputs[6]= ((FitsTreeItem) imageTree.getSelectedItem()).getTarget();
	  AsyncCallback<String[]> relatedCallback = new AsyncCallback<String[]>(){

		@Override
		public void onFailure(Throwable caught) {

		}

		@Override
		public void onSuccess(String[] result) {
			if(result.length == 0)
				Window.alert("Did not find any similar images");
			else{
				selectedImageTree.getItem(0).removeItems();
				for(int i = 0;i<result.length;i++)
				{
					FitsTreeItem similarFits = new FitsTreeItem(result[i].substring(result[i].lastIndexOf("/")+1).toLowerCase());
					similarFits.setPath(result[i].toLowerCase());
					similarFits.setJpgPath(parseFitsPathtoJpgPath(result[i]).toLowerCase());
					selectedImageTree.getItem(0).addItem(similarFits);
					similarPanel.hide();
					selectedImageTree.getItem(0).setState(true);
					scrollPanel.setWidget(selectedImageTree);
					treeTabBar.setWidth(treeFlexTable.getOffsetWidth()+"");
				}
			}
			
		}
		  
	  };
	  getRelatedServiceSvc.getRelatedFits(inputs, relatedCallback);
  }
  public String parseFitsPathtoJpgPath(String fitsPath)
  {
	  return fitsPath.substring(0, fitsPath.lastIndexOf("/")+1)+ "jpg/" + parseFitsToString(fitsPath.substring(fitsPath.lastIndexOf("/")+1));
	  
  }
  /*
   * createServices()
   * initializes all usable services
   */
  public void createServices()
  {
	  fitsServiceSvc = GWT.create(FitsDataService.class);
	  zoomJpegServiceSvc = GWT.create(ZoomJpegService.class);
	  treeDataServiceSvc = GWT.create(TreeDataService.class);
	  fitsHeaderServiceSvc = GWT.create(FitsHeaderService.class);
	  linkToJpgServiceSvc = (LinkToJPGServiceAsync) GWT.create(LinkToJPGService.class);	  
	  getRelatedServiceSvc = (GetRelatedServiceAsync)GWT.create(GetRelatedService.class);
	  fitsIDServiceSvc = GWT.create(FitsIDService.class);
  }

}
